package edu.stonybrook.cs.gars.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

import edu.stonybrook.cs.gars.shared.users.LoggedInUser;

public class LoginPanel extends Composite {
	private final GARS gars;
	private final Button signInButton;
	private final TextBox usernameTextBox;
	private final PasswordTextBox passwordPasswordTextBox;
	private final Label errorLabel;
	private final DialogBox dialogBox;
	private final Button closeButton;
	private final Label textToServerLabel;
	private final HTML serverResponseLabel;
	private final Label usernameLabel;
	private final Label passwordLabel;
	@UiField
	VerticalPanel verticalPanel;

	/**
	 * The message displayed to the user when the server cannot be reached or
	 * returns an error.
	 */
	private static final String SERVER_ERROR = "An error occurred while "
			+ "attempting to contact the server. Please check your network "
			+ "connection and try again.";

	/**
	 * Create a remote service proxy to talk to the server-side Authentication
	 * service.
	 */
	private final AuthenticationServiceAsync authenticationService = GWT
			.create(AuthenticationService.class);

	LoginPanel(final GARS gars) {
		this.gars = gars;

		signInButton = new Button("Sign In");
		usernameTextBox = new TextBox();
		passwordPasswordTextBox = new PasswordTextBox();
		errorLabel = new Label();

		initWidget(uiBinder.createAndBindUi(this));

		// We can add style names to widgets

		this.addStyleName("loginDockLayoutPanel");
		usernameTextBox.addStyleName("usernameTextBox");
		passwordPasswordTextBox.addStyleName("passwordPasswordTextBox");
		verticalPanel.addStyleName("verticalPanel");
		signInButton.setStyleName("signInButton");

		usernameLabel = new Label("Username:");
		usernameLabel.addStyleName("usernameLabel");
		passwordLabel = new Label("Password:");
		passwordLabel.addStyleName("passwordLabel");

		verticalPanel.add(usernameLabel);
		verticalPanel.add(usernameTextBox);
		verticalPanel.add(passwordLabel);
		verticalPanel.add(passwordPasswordTextBox);
		verticalPanel.add(signInButton);

		// RootLayoutPanel.get().add(errorLabel);

		// Focus the cursor on the name field when the app loads
		usernameTextBox.setFocus(true);
		usernameTextBox.selectAll();

		// Create the popup dialog box
		dialogBox = new DialogBox();
		dialogBox.setText("Remote Procedure Call");
		dialogBox.setAnimationEnabled(true);
		closeButton = new Button("Close");
		// We can set the id of a widget by accessing its Element
		closeButton.getElement().setId("closeButton");
		textToServerLabel = new Label();
		serverResponseLabel = new HTML();
		VerticalPanel dialogVPanel = new VerticalPanel();
		dialogVPanel.addStyleName("dialogVPanel");
		dialogVPanel
				.add(new HTML("<b>Sending login information to server:</b>"));
		dialogVPanel.add(textToServerLabel);
		dialogVPanel.add(new HTML(
				"<br><b>Your session id assigned by the server: </b>"));
		dialogVPanel.add(serverResponseLabel);
		dialogVPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
		dialogVPanel.add(closeButton);
		dialogBox.setWidget(dialogVPanel);

		// Add a handler to close the DialogBox
		closeButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				dialogBox.hide();
				signInButton.setEnabled(true);
				signInButton.setFocus(true);
			}
		});

		// Create a handler for the sendButton and nameField
		class MyHandler implements ClickHandler, KeyUpHandler {
			/**
			 * Fired when the user clicks on the sendButton.
			 */
			@Override
			public void onClick(ClickEvent event) {
				login(gars);
			}

			/**
			 * Fired when the user types in the nameField.
			 */
			@Override
			public void onKeyUp(KeyUpEvent event) {
				if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
					login(gars);
				}
			}

		}

		// Add a handler to send the name to the server
		MyHandler handler = new MyHandler();
		signInButton.addClickHandler(handler);
		usernameTextBox.addKeyUpHandler(handler);

	}

	/**
	 * Send the name from the nameField to the server and wait for a response.
	 */
	private void login(final GARS gars) {
		// First, we validate the input.
		errorLabel.setText("");
		final String username = usernameTextBox.getText();
		String password = passwordPasswordTextBox.getText();

		// TODO Client side field validation
		/*
		 * if (!FieldVerifier.isValidName(textToServer)) {
		 * errorLabel.setText("Please enter at least four characters"); return;
		 * }
		 */

		// Then, we send the input to the server.
		signInButton.setEnabled(false);
		textToServerLabel.setText("Username: " + username + "\nPassword: "
				+ password);
		serverResponseLabel.setText("");
		authenticationService.authenticate(username, password,
				new AsyncCallback<LoggedInUser>() {
					@Override
					public void onFailure(Throwable caught) {
						// Show the RPC error message to the user
						dialogBox.setText("Login Failed");
						serverResponseLabel
								.addStyleName("serverResponseLabelError");
						serverResponseLabel.setHTML(caught.getMessage());
						System.out.println(caught.getMessage());
						dialogBox.center();
						closeButton.setFocus(true);
					}

					@Override
					public void onSuccess(LoggedInUser loggedInUser) {
						

						gars.swapPanel(LoginPanel.this,
								gars.getApplicationTablePanel());
								
						//dialogBox.setText(result);
						LoginPanel.this.gars.setLoggedInUser(loggedInUser);
						serverResponseLabel.setText(loggedInUser.getSessionID() + " " + "Username: " + loggedInUser.getUsername() + " " + "Role: " + loggedInUser.getRole());
						dialogBox.setText("Welcome back, " + username + "!");
						dialogBox.center();
						closeButton.setFocus(true);
						signInButton.setEnabled(true);
					}
				});
	}

	private static LoginPanelUIBinder uiBinder = GWT
			.create(LoginPanelUIBinder.class);

	interface LoginPanelUIBinder extends UiBinder<Widget, LoginPanel> {
	}

}
